﻿using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
//susing Microsoft.Expression.Interactivity.Core;
using System.Windows;
using System.IO;
using GalaSoft.MvvmLight.Command;
using System;
using playlist.Properties;
using System.Windows.Markup;

namespace playlist
{
    class PlayListViewModel : INotifyPropertyChanged
    {
        #region EVENTS

        public event PropertyChangedEventHandler PropertyChanged; 
        public event EventHandler Play;
        public event EventHandler Pause;

        #endregion
        
        #region ATTRIBUTES

        private List<string> playLists_;
        private List<string> mediaPlayList_;
        private List<string> dirSearcher_;
        private int mediaPlayListsIndex_;
        private int playListsIndex_;
        private int currMediaPlayListIndex_;
        private int currPlayListsIndex_;
        private int themeIndex_;
        private double volume_;
        private PlayListsModel playListsModel_;
        private string mediaFileName_;
        private string newPlayListName_;
        private string mute_;

        #endregion ATTRIBUTES

        #region COMMAND_RELAYERS

        public RelayCommand PlayCmd { get; set; }
        public RelayCommand PlayPlayListCmd { get; set; }
        public RelayCommand PauseCmd { get; set; }
        public RelayCommand MediaEndedCmd { get; set; }
        public RelayCommand MuteCmd { get; set; }
        public RelayCommand PreviousMediaCmd { get; set; }
        public RelayCommand NextMediaCmd { get; set; }
        public RelayCommand SelectPlayListCmd { get; set; }
        public RelayCommand DeletePlayListCmd { get; set; }
        public RelayCommand DeleteMediaCmd { get; set; }
        public RelayCommand AddPlayListCmd { get; set; }
        public RelayCommand CloseWindowCmd { get; set; }
        public RelayCommand ChangeThemeCmd { get; set; }
        public RelayCommand<DragEventArgs> DragCmd { get; private set; }

        #endregion

        #region PROPERTIES

        public string MediaFilePath
        {
            get { return mediaFileName_; }
            set
            {
                if (mediaFileName_ != value)
                {
                    mediaFileName_ = value;
                    OnPropertyChanged("MediaFilePath");
                }
            }
        }

        public double Volume
        {
            get { return volume_; }
            set
            {
                if (volume_ != value)
                {
                    if (value == 0)
                        Mute = "Unmute";
                    else
                        Mute = "Mute";
                    volume_ = value;
                    OnPropertyChanged("Volume");
                }
            }
        }

        public string Mute
        {
            get { return mute_; }
            set
            {
                if (mute_ != value)
                {
                    mute_ = value;
                    OnPropertyChanged("Mute");
                }
            }
        }

        public string NewPlayListName
        {
            get { return newPlayListName_; }
            set
            {
                if (newPlayListName_ != value)
                {
                    newPlayListName_ = value;
                    OnPropertyChanged("NewPlayListName");
                }
            }
        }

        public List<string> MediaPlayList
        {
            get { return this.mediaPlayList_; }
            set
            {
                List<string> l = new List<string>(value);
                for (int i = 0; i < l.Count; i++)
                    l[i] = Path.GetFileNameWithoutExtension(l[i]);
                for (int i = 0; i < l.Count; i++)
                {
                    int count = 0;
                    for (int i1 = 0; i1 < l.Count; i1++)
                        if (l[i1] == l[i])
                            count++;
                    if (count > 1)
                        l[i] = l[i] + "(" + (count - 1) + ")";
                }
                if (this.mediaPlayList_ != l)
                {
                    this.mediaPlayList_ = l;
                    OnPropertyChanged("MediaPlayList");
                }
            }
        }

        public List<string> PlayLists
        {
            get { return this.playLists_; }
            set
            {
                if (this.playLists_ != value)
                {
                    this.playLists_ = value;
                    OnPropertyChanged("PlayLists");
                }
            }
        }

        public int MediaPlayListIndex
        {
            get { return this.mediaPlayListsIndex_; }
            set
            {
                if (mediaPlayListsIndex_ != value)
                {
                    mediaPlayListsIndex_ = value;
                    OnPropertyChanged("MediaPlayListIndex");
                }
            }
        }

        public int PlayListsIndex
        {
            get { return this.playListsIndex_; }
            set
            {
                if (playListsIndex_ != value)
                {
                    playListsIndex_ = value;
                    OnPropertyChanged("PlayListsIndex");
                }
            }
        }

        public int ThemeIndex
        {
            get { return this.themeIndex_; }
            set
            {
                if (this.themeIndex_ != value)
                {
                    themeIndex_ = value;
                    OnPropertyChanged("ThemeIndex");
                }
            }
        }

        #endregion

        #region CTOR
        public PlayListViewModel()
        {
            DynamicLoadStyles("ResourceDictionary1.xaml");

            this.playListsModel_ = new PlayListsModel("");
            this.PlayLists = this.playListsModel_.PlayListsDic.Keys.ToList();
            this.MediaPlayList = this.playListsModel_.PlayListsDic.First().Value.MediaDic.Values.ToList();
            this.PlayListsIndex = 0;
            this.MediaPlayListIndex = 0;
            this.ThemeIndex = 0;
            this.Volume = 0;
            this.currMediaPlayListIndex_ = -1;
            this.currPlayListsIndex_ = -1;
            this.Mute = "Unmute";
            this.InitCommands();
        }
        #endregion

        #region COMMANDS

        private void InitCommands()
        {
            this.PauseCmd = new RelayCommand(e =>
            {
                Pause.Invoke(this, EventArgs.Empty);
            });

            this.MuteCmd = new RelayCommand(e =>
            {
                if (this.Volume > 0)
                    this.Volume = 0;
                else
                    this.Volume = 0.5;
            });

            this.DeleteMediaCmd = new RelayCommand(e =>
            {
                MediaFilePath = "";
                if (this.MediaPlayListIndex == -1 || 
                    PlayListsIndex == -1 ||
                    this.playListsModel_.PlayListsDic.ElementAt(this.PlayListsIndex).Value.MediaDic.Count() == 0)
                    return;

                int delMediaPlayListIndex = this.MediaPlayListIndex;
                string delMediaPath = this.playListsModel_.PlayListsDic.ElementAt(this.PlayListsIndex).Value.MediaDic.ElementAt(this.MediaPlayListIndex).Value;
                
                this.playListsModel_.PlayListsDic.ElementAt(this.PlayListsIndex).Value.MediaDic.Remove(
                     this.playListsModel_.PlayListsDic.ElementAt(this.PlayListsIndex).Value.MediaDic.ElementAt(this.MediaPlayListIndex).Key
                    );
                
                this.MediaPlayList = this.playListsModel_.PlayListsDic.ElementAt(this.PlayListsIndex).Value.MediaDic.Values.ToList();
                if (this.playListsModel_.PlayListsDic.ElementAt(PlayListsIndex).Value.MediaDic.Count() > delMediaPlayListIndex)
                    this.MediaPlayListIndex = delMediaPlayListIndex;
                else
                    this.MediaPlayListIndex = delMediaPlayListIndex - 1;
            });

            this.NextMediaCmd = new RelayCommand(e =>
            {
                MediaFilePath = "";
                if (this.MediaPlayListIndex == -1 || PlayListsIndex == -1)
                    return;
                this.currMediaPlayListIndex_ = this.MediaPlayListIndex;
                this.currPlayListsIndex_ = this.PlayListsIndex;
                this.MediaEndedCmd.Execute(null);
            });

            this.PreviousMediaCmd = new RelayCommand(e =>
            {
                MediaFilePath = "";
                if (this.MediaPlayListIndex == -1 || PlayListsIndex == -1)
                    return;
                this.currMediaPlayListIndex_ = this.MediaPlayListIndex;
                this.currPlayListsIndex_ = this.PlayListsIndex;
                if (this.MediaPlayListIndex - 1 > -1)
                {
                    this.MediaPlayListIndex -= 1;
                    this.PlayCmd.Execute(null);
                }
            });
            
            this.MediaEndedCmd = new RelayCommand(e =>
            {
                MediaFilePath = "";
                if (this.currMediaPlayListIndex_ == -1 || this.currPlayListsIndex_ == -1)
                    return;
                if (this.playListsModel_.PlayListsDic.ElementAt(this.currPlayListsIndex_).Value.MediaDic.Count() > this.currMediaPlayListIndex_ + 1)
                {
                    if (this.MediaPlayListIndex == this.currMediaPlayListIndex_)
                        this.MediaPlayListIndex += 1;
                    this.currMediaPlayListIndex_ += 1;
                    this.PlayCmd.Execute(null);
                }
            });

            this.PlayCmd = new RelayCommand(e =>
            {
                if (this.currMediaPlayListIndex_ > -1 && currPlayListsIndex_ > -1)
                {
                    if (this.playListsModel_.PlayListsDic.ElementAt(currPlayListsIndex_).Value.MediaDic.Count() > 0)
                        MediaFilePath = this.playListsModel_.PlayListsDic.ElementAt(currPlayListsIndex_).Value.MediaDic.ElementAt(currMediaPlayListIndex_).Value;
                    if (Play != null)
                        Play.Invoke(this, EventArgs.Empty);
                }
                Play.Invoke(this, EventArgs.Empty);
            });

            this.PlayPlayListCmd = new RelayCommand(e =>
            {
                if (this.currMediaPlayListIndex_ != this.MediaPlayListIndex &&
                    this.currPlayListsIndex_ != this.PlayListsIndex)
                MediaFilePath = "";
                this.currMediaPlayListIndex_ = this.MediaPlayListIndex;
                this.currPlayListsIndex_ = this.PlayListsIndex;
                this.PlayCmd.Execute(null);
            });

            this.ChangeThemeCmd = new RelayCommand(e =>
            {
                if (this.ThemeIndex == 0)
                    DynamicLoadStyles("ResourceDictionary1.xaml");
                else
                    DynamicLoadStyles("ResourceDictionary2.xaml");

            });

            this.DragCmd = new RelayCommand<DragEventArgs>(e =>
            {
                if (e.Data == null)
                    return;

                var files = e.Data.GetData(DataFormats.FileDrop, true)
                   as string[];

                if (files == null || files.Length == 0)
                    return;
                List<string> concat = new List<string>();
                this.dirSearcher_ = new List<string>();
                foreach (string file in files)
                {
                    if (this.IsADirectory(file))
                    {
                        this.DirSearch(file);
                        concat = concat.Concat(this.dirSearcher_).ToList();
                    }
                    else if (this.IsAMediaFile(file))
                    {
                        concat.Add(file);
                    }
                }
                if (this.PlayListsIndex > -1)
                {
                    this.playListsModel_.AddInPlayList(this.PlayListsIndex, concat);
                    this.MediaPlayList = this.playListsModel_.PlayListsDic.ElementAt(this.PlayListsIndex).Value.MediaDic.Values.ToList();
                }
            });

            this.SelectPlayListCmd = new RelayCommand(e =>
            {
                if (this.PlayListsIndex == -1)
                    return;
                  this.MediaPlayList = this.playListsModel_.PlayListsDic.ElementAt(this.PlayListsIndex).Value.MediaDic.Values.ToList();
                  if (this.currMediaPlayListIndex_ != -1 && (this.PlayListsIndex == this.currPlayListsIndex_))
                      this.MediaPlayListIndex = this.currMediaPlayListIndex_;
            });

            this.CloseWindowCmd = new RelayCommand(e =>
            {
                this.playListsModel_.Save();
            });

            this.DeletePlayListCmd = new RelayCommand(e =>
            {
                if (this.currPlayListsIndex_ == this.PlayListsIndex)
                    this.MediaFilePath = "";
                this.playListsModel_.PlayListsDic.Remove(this.playListsModel_.PlayListsDic.ElementAt(this.PlayListsIndex).Key);
                if (this.playListsModel_.PlayListsDic.Count == 0)
                {
                    this.playListsModel_.AddDefaultPlaylist();
                }
                this.PlayLists = this.playListsModel_.PlayListsDic.Keys.ToList();
                this.MediaPlayList = this.playListsModel_.PlayListsDic.First().Value.MediaDic.Values.ToList();
                this.PlayListsIndex = 0;
                this.MediaPlayListIndex = 0;
            });

            this.AddPlayListCmd = new RelayCommand(e =>
            {
                string playListName = this.NewPlayListName;
                if (playListName == null)
                    this.playListsModel_.AddDefaultPlaylist(this.playListsModel_.PlayListsDic.Count());
                else
                    this.playListsModel_.AddPlaylist(playListName);
                this.PlayLists = this.playListsModel_.PlayListsDic.Keys.ToList();
                this.MediaPlayList = this.playListsModel_.PlayListsDic.First().Value.MediaDic.Values.ToList();
                this.PlayListsIndex = 0;
                this.MediaPlayListIndex = 0;
                this.NewPlayListName = null;
            });
        }

        #endregion

        #region METHODS

        private void DynamicLoadStyles(string txtXamlName)
        {
            string fileName;

            fileName =".\\" + txtXamlName;

            if (File.Exists(fileName))
            {
                using (FileStream fs = new FileStream(fileName, FileMode.Open))
                {
                    ResourceDictionary dic = (ResourceDictionary)XamlReader.Load(fs);
                    Application.Current.Resources.MergedDictionaries.Add(dic);
                }
            } 
        }

        protected void OnPropertyChanged(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(name));
        }

        private void DirSearch(string sDir)
        {
            string[] arrFolder = { };
            try
            {
                arrFolder = Directory.GetDirectories(sDir);
            }
            catch { }

            foreach (string fo in arrFolder)
            {
                try
                {
                    foreach (string f in Directory.GetFiles(fo))
                    {
                        if (IsAMediaFile(f))
                        {
                            this.dirSearcher_.Add(f);
                        }
                    }
                    DirSearch(fo);
                }
                catch { }
            }
        }

        private bool IsADirectory(string path)
        {
            bool bIsDirectory = true;

            try
            { string[] subfolders = Directory.GetDirectories(path); }
            catch 
            { bIsDirectory = false; }
            return bIsDirectory;
        }

        private bool IsAMediaFile(string file)
        {
            string sPattern = "\\.mp3|\\.mp4|\\.wmv|\\.avi|\\.mpg|\\.3gp|\\.jpg|\\.bmp|\\.png";
            if (System.Text.RegularExpressions.Regex.IsMatch(file, sPattern))
                return true;
            return false;
        }

        #endregion

    }
}
